﻿using System;
using System.Linq;
using System.Reflection;
using System.Text;
using Properties;

namespace Borg
{
    public class ParamDefinition : RepositoryMetaElement
    {
        internal static int nextId = 1;
        internal static readonly object NoDefaultValue = new object();

        internal static QualificationState unqualifiedState =
            QualificationState.QualificationMissing |
            QualificationState.ParamDefinitionAlreadyExists |
            QualificationState.ParamDefinitionEmptyName;

        internal readonly ParamAttribute paramAttribute;
        internal SlotDefinition slotDefinition;

        public override string Name
        {
            get { return paramAttribute.Name; }
        }

        public override Assembly Assembly
        {
            get { return slotDefinition.contractInfo.assembly; }
        }

        public Type Type
        {
            get { return Type.GetType(paramAttribute.Type.AssemblyQualifiedName); }
        }

        public object DefaultValue
        {
            get { return paramAttribute.DefaultValue; }
        }

        public bool HasDefaultValue
        {
            get { return DefaultValue != NoDefaultValue; }
        }

        public override bool IsQualified
        {
            get { return (qualificationState & unqualifiedState) == QualificationState.None; }
        }

        static ParamDefinition()
        { }

        internal ParamDefinition(SlotDefinition slotDefinition, ParamAttribute paramAttribute)
        {
            id = nextId++;
            this.slotDefinition = slotDefinition;
            this.paramAttribute = paramAttribute;
        }

        internal override QualificationState InternalQualify()
        {
            var builder = new StringBuilder();

            if (string.IsNullOrEmpty(Name))
            {
                builder.AppendFormat("\n  {0}", Messages.ParameterNameEmpty);
                var paramDef = this;
                var status = (long)(paramDef.qualificationState | QualificationState.ParamDefinitionEmptyName);
                paramDef.qualificationState = (QualificationState)status;
            }

            if (slotDefinition.paramDefinitions.Any(paramDef => paramDef != this &&
                paramDef.Name == Name && paramDef.IsQualified))
            {
                builder.AppendFormat("\n  {0}", Messages.ParameterAlreadyDefined);
                var paramDefinition = this;
                var status = (long)(paramDefinition.qualificationState | QualificationState.ParamDefinitionAlreadyExists);
                paramDefinition.qualificationState = (QualificationState)status;
            }

            var parmDef = this;
            var stat = (long)(parmDef.qualificationState & ~QualificationState.QualificationMissing);
            parmDef.qualificationState = (QualificationState)stat;

            RuntimeBase.LogQualifyResult(
                this,
                qualificationState,
                unqualifiedState,
                QualificationState.None,
                Messages.QualifyParamDefinition,
                builder.ToString());

            return qualificationState;
        }
    }
}

